home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 19 / CU Amiga Magazine's Super CD-ROM 19 (1998)(EMAP Images)(GB)[!][issue 1998-02].iso / CUCD / Programming / LEDA / source / src / graph_alg / _triang.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-16  |  4.4 KB  |  144 lines

  1. /*******************************************************************************
  2. +
  3. +  LEDA  3.1c
  4. +
  5. +
  6. +  _triang.c
  7. +
  8. +
  9. +  Copyright (c) 1994  by  Max-Planck-Institut fuer Informatik
  10. +  Im Stadtwald, 6600 Saarbruecken, FRG     
  11. +  All rights reserved.
  12. *******************************************************************************/
  13.  
  14.  
  15.  
  16. /******************************************************************************
  17. *                                                                              *
  18. *  TRIANGULATE_PLANAR_MAP  (triangulation)                                     *
  19. *                                                                              *
  20. *******************************************************************************/
  21.  
  22. #include <LEDA/graph_alg.h>
  23.  
  24. #define NEXT_FACE_EDGE(e) G.cyclic_adj_pred(REV[e]) 
  25.  
  26. list<edge> TRIANGULATE_PLANAR_MAP(graph& G)
  27.  
  28. /* G is a planar map. This procedure triangulates all faces of G
  29.    without introducing multiple edges. The algorithm was suggested by 
  30.    Christian Uhrig and Torben Hagerup. 
  31.  
  32.    Description:
  33.  
  34.    Triangulating a planar graph G, i.e., adding edges
  35.    to G to obtain a chordal planar graph, in linear time:
  36.    
  37.    1) Compute a (combinatorial) embedding of G.
  38.    
  39.    2) Step through the vertices of G. For each vertex u,
  40.    triangulate those faces incident on u that have not
  41.    already been triangulated. For each vertex u, this
  42.    consists of the following:
  43.    
  44.      a) Mark the neighbours of u. During the processing
  45.    of u, a vertex will be marked exactly if it is a
  46.    neighbour of u.
  47.    
  48.      b) Process in any order those faces incident on u
  49.    that have not already been triangulated. For each such
  50.    face with boundary vertices u=x_1,...,x_n,
  51.         I)   If n=3, do nothing; otherwise
  52.         II)  If x_3 is not marked, add an edge {x_1,x_3},
  53.              mark x_3 and continue triangulating the face
  54.              with boundary vertices x_1,x_3,x_4,...,x_n.
  55.         III) If x_3 is marked, add an edge {x_2,x_4} and
  56.              continue triangulating the face with boundary
  57.              vertices x_1,x_2,x_4,x_5,...,x_n.
  58.    
  59.      c) Unmark the neighbours of x_1.
  60.    
  61.    Proof of correctness:
  62.    
  63.    A) All faces are triangulated.
  64.    This is rather obvious.
  65.    
  66.    B) There will be no multiple edges.
  67.    During the processing of a vertex u, the marks on
  68.    neighbours of u clearly prevent us from adding a multiple
  69.    edge with endpoint u. After the processing of u, such an
  70.    edge is not added because all faces incident on u have
  71.    been triangulated. This takes care of edges added in
  72.    step II).
  73.    Whenever an edge {x_2,x_4} is added in step III), the
  74.    presence of an edge {x_1,x_3} implies, by a topological
  75.    argument, that x_2 and x_4 are incident on exactly one
  76.    common face, namely the face currently being processed.
  77.    Hence we never add another edge {x_2,x_4}.
  78. */
  79.    
  80.   node v;
  81.   edge x;
  82.   list<edge> L;
  83.  
  84.   node_array<int>  marked(G,0);
  85.  
  86.   edge_array<edge> REV(G, 3*G.number_of_edges(), nil);
  87.  
  88.   if ( !compute_correspondence(G,REV)) 
  89.   error_handler(1,"TRIANGULATE_PLANAR_MAP: graph is not symmetric");
  90.  
  91.   forall_nodes(v,G)
  92.   {
  93.     list<edge> El = G.adj_edges(v);
  94.     edge e,e1,e2,e3;
  95.  
  96.     forall(e,El) marked[target(e)]=1;
  97.  
  98.     forall(e,El)
  99.     { 
  100.       e1 = e;
  101.       e2 = NEXT_FACE_EDGE(e1);
  102.       e3 = NEXT_FACE_EDGE(e2);
  103.  
  104.       while (target(e3) != v)
  105.       // e1,e2 and e3 are the first three edges in a clockwise 
  106.       // traversal of a face incident to v and t(e3) is not equal
  107.       // to v.
  108.        if ( !marked[target(e2)] )
  109.         { // we mark w and add the edge {v,w} inside F, i.e., after
  110.           // dart e1 at v and after dart e3 at w.
  111.  
  112.           marked[target(e2)] = 1;
  113.           L.append(x  = G.new_edge(e3,source(e1)));
  114.           L.append(e1 = G.new_edge(e1,source(e3)));
  115.           REV[x] = e1;
  116.           REV[e1] = x;
  117.           e2 = e3;
  118.           e3 = NEXT_FACE_EDGE(e2);
  119.         }
  120.         else
  121.         { // we add the edge {source(e2),target(e3)} inside F, i.e.,
  122.           // after dart e2 at source(e2) and before dart 
  123.           // reversal_of[e3] at target(e3).
  124.  
  125.           e3 = NEXT_FACE_EDGE(e3); 
  126.           L.append(x  = G.new_edge(e3,source(e2)));
  127.           L.append(e2 = G.new_edge(e2,source(e3)));
  128.           REV[x] = e2;
  129.           REV[e2] = x;
  130.         }
  131.      //end of while
  132.  
  133.     } //end of stepping through incident faces
  134.  
  135.    node w; forall_adj_nodes(w,v) marked[w] = 0;
  136.  
  137.   } // end of stepping through nodes
  138.  
  139. return L;
  140.  
  141. }
  142.